package vista.objetos;

import java.awt.Color;
import java.awt.Font;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Observable;

import javax.media.opengl.awt.GLJPanel;
import javax.swing.JFrame;

import controlador.ContenedorDeErrores;

import logica.ObjetoDiagrama;
import logica.persistencia.GraficableConEtiquetaPersistente;
import vista.paneles.hojaDibujo.HojaDeDibujo;
import vista.treeDiagrama.NodoTreeDiagrama;
import vista.treeDiagrama.TreeDeDiagrama;
import eventos.EventoEtiquetaDeGraficable;

public class ContenedorDeGraficables extends GraficableConEtiqueta implements IContenedorDeGraficable{

	private List<GraficableConEtiqueta> graficables = new LinkedList<>();
	
	public ContenedorDeGraficables()
	{
		super();
		this.getEtiqueta().setBackground(new Color(1.f, 0.f, 0.f));
		this.getEtiqueta().setOpaque(true);
	}
	
	@Override
	public void inicializarPosiciones()
	{
		Point centro, mouse, desplazamiento;
		int x2, y2;
		
		centro = calcularMedio();
		mouse = this.getPunto();
		desplazamiento = new Point(mouse.x - centro.x, mouse.y - centro.y);
		
		this.getEtiqueta().setLocation(mouse);
		
		for(GraficableConEtiqueta graf: this.graficables)
		{
			x2 = desplazamiento.x + graf.getPunto().x;
			y2 = desplazamiento.y + graf.getPunto().y;

			graf.setUbicacionEtiqueta(x2,y2);
		}
		
	}

	void setDiagrama(DiagramaGraficable diagrama) {
		for(GraficableConEtiqueta graf: this.graficables)
			graf.setDiagrama(diagrama);
	}

	private Point calcularMedio()
	{
		int xMin, xMax, yMin, yMax;
		Point pto;
		Iterator<GraficableConEtiqueta> it = this.getGraficables().iterator();

		if (!it.hasNext())
			return new Point();
		
		pto = it.next().getPunto().getLocation();

		xMin = xMax = pto.x;
		yMin = yMax = pto.y;
		
		while (it.hasNext())
		{
			pto = it.next().getPunto().getLocation();

			if (pto.x < xMin)
				xMin = pto.x;
			else if (pto.x > xMax)
				xMax = pto.x;
			
			if (pto.y < yMin)
				yMin = pto.y;
			else if (pto.y > yMax)
				yMax = pto.y;
		}
		
		return new Point((xMin+xMax)/2, (yMin+yMax)/2);
	}

	@Override
	public ObjetoDiagrama getObjetoDiagramaDecorado() throws NoEsObjetoDiagramableException {
		throw new NoEsObjetoDiagramableException(this.getClass()+" no tiene un ObjetoDiagrama asociado.");
	}

	@Override
	public NodoTreeDiagrama getNodoTreeDiagrama() throws NoEsObjetoNodoException {
		throw new NoEsObjetoNodoException(this.getClass()+ " no le corresponde ningún nodo y no es agregado al JTree.");
	}

	@Override
	public MouseAdapter getEventoEditarGraficable(JFrame ventanaPadre) {
		return null;
	}

	@Override
	public void dibujarse(Object areaDeDibujo) {
		for(GraficableConEtiqueta graf: this.graficables)
			graf.dibujarse(areaDeDibujo);
	}

	@Override
	public void agregarseAlCanvas(GLJPanel panel, Font fuente, Color color)	{	
		for(GraficableConEtiqueta graf: this.graficables)
			graf.agregarseAlCanvas(panel, fuente, color);
	}
	
	@Override
	public void setUbicacionEtiqueta(int nuevoX, int nuevoY)
	{
		Point desplazamiento = new Point(this.getEtiqueta().getLocation());
		desplazamiento.setLocation(nuevoX - desplazamiento.x, nuevoY - desplazamiento.y);
		super.setUbicacionEtiqueta(nuevoX, nuevoY);
		
		for(GraficableConEtiqueta graf: this.graficables)
			graf.dragGraficable(desplazamiento);
	}
	
	@Override
	public boolean esElGraficableDe(ObjetoDiagrama objeto) 
	{
		for(GraficableConEtiqueta graf: this.graficables)
			if (graf.esElGraficableDe(objeto))
				return true;
		
		return false;
	}

	@Override
	public void update(Observable o, Object arg) {}

	@Override
	protected EventoEtiquetaDeGraficable getEvento(HojaDeDibujo hoja) {
		return new EventoEtiquetaDeGraficable(hoja, this);
	}

	@Override
	public GraficableConEtiquetaPersistente getGraficableConEtiquetaPersistente() {
		return null;
	}

	@Override
	public boolean tieneLaEntidad(EntidadGraficable entidadGraficable)
	{
		for(GraficableConEtiqueta graf: this.graficables)
			if (graf.tieneLaEntidad(entidadGraficable))
				return true;
		
		return false;
	}

	@Override
	public boolean sePuedeBorrar(EntidadGraficable entidadGraficable) {
		return false;
	}

	public List<GraficableConEtiqueta> getGraficables() {
		return graficables;
	}
	
	@Override
	public void agregarseAlArbol(TreeDeDiagrama arbolDeDiagrama)
	{
		for(GraficableConEtiqueta graf: this.graficables)
			graf.agregarseAlArbol(arbolDeDiagrama);
	}
	
	@Override
	public void agregarseAlDiagrama(DiagramaGraficable diagramaGraficable)
	{
		for(GraficableConEtiqueta graf: this.graficables)
		{
			graf.setDiagrama(diagramaGraficable);
			diagramaGraficable.getGraficables().add(graf);
		}
	}
	
	@Override
	public void agregarEventoEtiqueta(HojaDeDibujo hoja)
	{
		for(GraficableConEtiqueta graf: this.graficables)
			graf.agregarEventoEtiqueta(hoja);
	}
	
	@Override
	public void setNodo() throws NoEsObjetoNodoException 
	{
		for(GraficableConEtiqueta graf: this.graficables)
			graf.setNodo();
	}
	
	@Override
	public void setPopupMenu() {
		for(GraficableConEtiqueta graf: this.graficables)
			graf.setPopupMenu();
	}
	
	@Override
	public void escucharEventoEditar(JFrame ventanaPadre) {
		for(GraficableConEtiqueta graf: this.graficables)
			graf.escucharEventoEditar(ventanaPadre);
	}
	
	@Override
	public void nodoEscucharEventoEditar(JFrame ventanaPadre) {
		for(GraficableConEtiqueta graf: this.graficables)
			graf.nodoEscucharEventoEditar(ventanaPadre);
	}

	@Override
	public void borrarseDeLaHoja() {
		for(GraficableConEtiqueta graf: this.graficables){
			graf.borrarseDeLaHoja();
		}
	}

	@Override
	public void agregarGraficable(GraficableConEtiqueta graficable) {
		this.getGraficables().add(graficable);
	}

	@Override
	public GraficableConEtiqueta copiarse(IContenedorDeGraficable contenedor) {
		return null;
	}

	@Override
	public boolean estaElGraficable(GraficableConEtiqueta graficable)
	{
		try 
		{
			for (GraficableConEtiqueta graficableEnContenedor: this.getGraficables())
					if (graficableEnContenedor.getObjetoDiagramaDecorado() == graficable.getObjetoDiagramaDecorado())
						return true;
		} catch (NoEsObjetoDiagramableException e) {
				e.printStackTrace();
		}
		
		return false;
	}

	@Override
	public GraficableConEtiqueta getGraficableCopiaDe(GraficableConEtiqueta graficable) 
	{
		try 
		{
			for (GraficableConEtiqueta graficableEnContenedor: this.getGraficables())
					if (graficableEnContenedor.getObjetoDiagramaDecorado() == graficable.getObjetoDiagramaDecorado())
						return graficableEnContenedor;
		} catch (NoEsObjetoDiagramableException e) {
				e.printStackTrace();
		}
		
		return null;
	}

	@Override
	public void agregarObjeto(ObjetoDiagrama objeto) {}

	@Override
	public void validar(ContenedorDeErrores errores) {}
}
